package com.theaf.basemodule.service.impl;

import com.theaf.basemodule.common.api.DataExService;
import com.theaf.basemodule.common.api.OrganService;
import com.theaf.basemodule.common.dto.organ.*;
import com.theaf.basemodule.common.model.SysArea;
import com.theaf.basemodule.common.model.SysOrg;
import com.theaf.basemodule.dao.AreaDAO;
import com.theaf.basemodule.dao.OrganDAO;
import com.theaf.basemodule.dao.UserDAO;
import com.theaf.basemodule.service.constants.StateConstant;
import com.theaf.core.cache.RedisHelper;
import com.theaf.core.error.SmExceptionHelper;
import com.theaf.core.repo.specification.SqlBuilder;
import com.theaf.core.repo.specification.SqlOperator;
import com.theaf.core.repo.specification.SqlValue;
import com.theaf.core.repo.specification.SubqueryEx;
import com.theaf.core.utils.BeanUtils;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @Author:songwenke
 * @Description:机构服务
 * @Date:create in 16:57 2018/1/29
 * @Modified By:
 **/
@Service
public class OrganServiceImpl implements OrganService {
    private final static String ORGAN_TYPE = "organ_type";
    @Autowired
    private OrganDAO organDAO;
    @Autowired
    private DataExService dataExService;
    @Autowired
    private AreaDAO areaDAO;
    @Autowired
    private UserDAO userDAO;
    @Autowired
    private Mapper mapper;
    private static String PIONT = ".";
    private static long top_organ_id=108;
    @Override
    public List<OrganDTO> findForTree(String name, String type, String creater, String updater, Long areaId, Boolean enabled,
                                      Date start, Date end, Long pid, int levelSize, String auths, Boolean delete, Map<String,Object> otherTerm) {
        SqlBuilder subBuilder = SqlBuilder.start(
                SqlBuilder.start("fullName", SqlOperator.OPER.LIKE,SqlValue.parse(name))
                                       .or("simpleName",SqlOperator.OPER.LIKE,SqlValue.parse(name)))
                .and("type", SqlValue.parse(type))
                .and("creater", SqlOperator.OPER.LIKE,SqlValue.parse(creater))
                .and("updater", SqlOperator.OPER.LIKE,SqlValue.parse(updater))
                .and("areaId",areaId);
        if(enabled!=null) {
            subBuilder.and("enabled", enabled);
        }else{
            subBuilder.and("enabled", true);
        }
        subBuilder.and("createTime",SqlOperator.OPER.GE,start)
                .and("createTime",SqlOperator.OPER.LEA,end)
                .and(SqlValue.parse(auths), SqlOperator.OPER.LIKES,"to_char(id)").setSelects(new String[]{"levelCode"});
        if(delete!=null){
            subBuilder.and("state",delete?SqlOperator.OPER.EQ:SqlOperator.OPER.NE,StateConstant.DELETE);
        }
        if(otherTerm!=null){
            for(String key:otherTerm.keySet()){
                subBuilder.and("others.fieldName",SqlValue.parse(key)).and("others.fieldValue",SqlValue.parse(otherTerm.get(key)));
            }
        }
        SubqueryEx subquery = organDAO.subquery(subBuilder);
        SqlBuilder builder = SqlBuilder.start("id",SqlOperator.OPER.NE,pid)
               .and(subquery,SqlOperator.OPER.LIKER,"levelCode");
        if(pid!=null){
            builder.and("levelCode",SqlOperator.OPER.LIKER,
                    organDAO.subquery(SqlBuilder.start("id", pid).setSelects(new String[]{"levelCode"})));
        }
        if(levelSize!=-1) {
            builder.and("length(levelCode)", SqlOperator.OPER.LE, levelSize*6);
        }
        List<SysOrg> sysOrgs  = organDAO.findAll(builder.gen());
        List<OrganDTO> organDTOS = new ArrayList();
        for(SysOrg sysOrg:sysOrgs) {
            OrganDTO organDTO = mapper.map(sysOrg,OrganDTO.class);
            organDTOS.add(organDTO);
        }
        return organDTOS;
    }

    @Override
    public List<OrganDTO> find(String name, Long parentId, String organType) {
        SqlBuilder builder = SqlBuilder.start(
                SqlBuilder.start("simpleName", SqlOperator.OPER.LIKE,SqlValue.parse(name))
                        .or("fullName", SqlOperator.OPER.LIKER,SqlValue.parse(name)))
                .and("pid",parentId).and("type",SqlValue.parse(organType));
        return (List<OrganDTO>) organDAO.findAll(builder.gen()).parallelStream().map(n->mapper.map(n,OrganDTO.class));
    }

    @Override
    public List<ContactDTO> findContact(String name, Long parentId, String organType, String contactCode) {
        SqlBuilder builder = SqlBuilder.start(
                SqlBuilder.start("simpleName", SqlOperator.OPER.LIKE,SqlValue.parse(name))
                        .or("fullName", SqlOperator.OPER.LIKER,SqlValue.parse(name)))
                .and("pid",parentId).and("type",SqlValue.parse(organType)).setSelects(new String[]{"id"});
        Map<String,String> map = new HashMap();
        if(contactCode!=null) {
            map.put("code", contactCode);
        }
        return null;
        //return dataExService.find("organ",null,"contactDTOList",ContactDTO.class,organDAO.subquery(builder),map);
    }

    @Override
    public List<ContactDTO> findContact(Long id,String contactCode){
        Map<String,String> map = new HashMap();
        if(contactCode!=null) {
            map.put("code", contactCode);
        }
        return null;
        //return dataExService.find("organ",null,"contactDTOList",ContactDTO.class,id==null?null:Arrays.asList(id),map);
    }

    /**
     * 对象查询
     * @param id
     * @return
     */
    @Override
    public OrganDTO findById(Long id){
        SysOrg sysOrg = organDAO.findOne(id);
        if(sysOrg==null){
            throw SmExceptionHelper.sysCheckException("非知机构");
        }
        OrganDTO organDTO = null;
        //门店
        if(ShopDTO.CHAN_SHOP.equals(sysOrg.getType())){//门店
            organDTO = new ShopDTO();
        }else if(MallSupDTO.MALL_SUP.equals(sysOrg.getType())) {//用品供应商
            organDTO = new MallSupDTO();
        }else if(PartsSupDTO.PARTS_SUP.equals(sysOrg.getType())){//配件供应商
            organDTO = new PartsSupDTO();
        }else {
            organDTO = new OrganDTO();
        }
        mapper.map(sysOrg,organDTO);
        /*dataExService.setDTODataFromPo("organ",sysOrg.getType(),organDTO, sysOrg.getOthers());
        organDTO.setTypeName(DictionaryHelper.getChlidValue(ORGAN_TYPE,organDTO.getType()));
        if(organDTO.getAreaId()!=null) {
            organDTO.setAreaName(areaDAO.findOne(organDTO.getAreaId()).getName());
        }
        if(sysOrg.getPoster()!=null) {
            organDTO.setPosterName(userDAO.findOne(sysOrg.getPoster()).getCname());
        }*/
        return organDTO;
    }

    @Override
    public Long save(Object v) throws Exception{
        boolean add = true;
        SysOrg sysOrgan = new SysOrg();
        Long id = (Long)BeanUtils.getProperty(v,"id");
        Long pid = (Long)BeanUtils.getProperty(v,"pid");
        Long areaId = (Long)BeanUtils.getProperty(v,"areaId");
        String type = (String)BeanUtils.getProperty(v,"type");
        if(id!=null&&organDAO.exists(id)){
            add = false;
            sysOrgan = organDAO.findOne(id);
            sysOrgan.setState(StateConstant.UPDATE);
        }else {
            BeanUtils.setProperty(sysOrgan,"id",null);
            BeanUtils.setProperty(sysOrgan,"state", StateConstant.ADD);
        }
        if(pid!=null&&!organDAO.exists(pid)){
            throw SmExceptionHelper.sysCheckException(pid+"父机构不存在");
        }
        if(areaId!=null&&!areaDAO.exists(areaId)){
            throw SmExceptionHelper.sysCheckException(areaId+"地区不存在");
        }
        mapper.map(v,sysOrgan);
        if(sysOrgan.getAreaId()!=null) {
            SysArea area = areaDAO.getOne(sysOrgan.getAreaId());
            if (area != null) {
                //sysOrgan.setAreaLevelCode(area.getLevelCode());
            }
        }
        //如果父ID改变，需要初始化层级
        if(add||organDAO.judgeChange(sysOrgan.getId(),"pid",sysOrgan.getPid())){
            organDAO.initLevel(sysOrgan,"levelCode","id","pid");
        }
        organDAO.save(sysOrgan);
        RedisHelper.clearByPrefix(UserServiceImpl.REDIS_DATA_RANGE);
        //dataExService.savePoOther(id,v,"organ",type);
        return sysOrgan.getId();
    }

    private Object getPathData(Object dto,String path){
        String[] ps = path.split("\\.");
        Object pre = dto;
        for(String p:ps){
            try {
                Object ref = null;
                if(pre instanceof Collection){
                    ref = new ArrayList();
                    for(Object pre_item:(Collection)pre) {
                        Object refs = BeanUtils.getProperty(pre_item, p);
                        if(refs instanceof Collection) {
                            ((Collection) ref).addAll((Collection) refs);
                        }else {
                            ((Collection) ref).add(refs);
                        }
                    }
                }else{
                    ref = BeanUtils.getProperty(pre, p);
                }
                pre = ref;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return pre;
    }

    @Override
    public void delete(Long id) {
        SysOrg sysOrg = organDAO.findOne(id);
        sysOrg.setState(StateConstant.DELETE);
        organDAO.save(sysOrg);
    }

    @Override
    public void openOrClose(Long id) {
        SysOrg sysOrg = organDAO.findOne(id);
        sysOrg.setEnabled(!sysOrg.isEnabled());
        organDAO.save(sysOrg);
    }

    @Override
    public void move(List<Long> ids, Long parentId) {
        for(Long id:ids){
            SysOrg sysOrg = organDAO.findOne(id);
            sysOrg.setPid(parentId);
            organDAO.initLevel(sysOrg,"levelCode","id","pid");
        }
    }

    /**
     * 获取子机构ID
     * @param id
     * @return
     */
    @Override
    public List<Long> findChildAllId(Long id) {
        return organDAO.findChildAllId(id);
    }

    /**
     * 获取所有子机构ID
     * @param id
     * @return
     */
    @Override
    public List<Long> findChildId(Long id){
        return organDAO.findChildId(id);
    }

    @Override
    public List<OrganDTO> findAllChild(Long id) {
        return (List<OrganDTO>)organDAO.findChildAll(id).parallelStream().map(n->mapper.map(n,OrganDTO.class));
    }

    @Override
    public List<ContactDTO> findAllChildContact(Long id,String contactCode) {
        SqlBuilder builder = SqlBuilder.start("levelCode", SqlOperator.OPER.LIKER,
                organDAO.subquery(SqlBuilder.start("id",id).setSelects(new String[]{"levelCode"}))).setSelects(new String[]{"id"});
        Map<String,String> map = new HashMap();
        if(contactCode!=null) {
            map.put("code", contactCode);
        }
        //return dataExService.find("organ",null,"contactDTOList",ContactDTO.class,id==null?null:organDAO.subquery(builder),map);
        return null;
    }

    @Override
    public List<OrganDTO> findChild(Long id) {
        return (List<OrganDTO>)organDAO.findChild(id).parallelStream().map(n->mapper.map(n,OrganDTO.class));
    }

    @Override
    public List<ContactDTO> findChildContact(Long id,String contactCode) {
        SqlBuilder builder = SqlBuilder.start("pid",id).or("id",id).setSelects(new String[]{"id"});
        Map<String,String> map = new HashMap();
        if(contactCode!=null) {
            map.put("code", contactCode);
        }
        //return dataExService.find("organ",null,"contactDTOList" ,ContactDTO.class,id==null?null:organDAO.subquery(builder),map);
        return null;
    }
}
